package cn.otrue.patienthealthmanager.view;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
 * 日历控件 功能：获得点选的日期区间
 * 
 */
public class CalendarView extends View implements View.OnTouchListener {
	private final static String TAG = "anCalendar";
	private static final int REQUEST_HEALTH_DATA = 105;
	private Date selectedStartDate;
	private Date selectedEndDate;
	private Date curDate; // 当前日历显示的月
	private Date downDate; // 手指按下状态时临时日期
	private Date showFirstDate, showLastDate; // 日历显示的第一个日期和最后一个日期
	private int downIndex; // 按下的格子索引
	private Calendar calendar;
	private Surface surface;
	private int[] date = new int[42]; // 日历显示数字
	private int curStartIndex, curEndIndex; // 当前显示的日历起始的索引
	// 给控件设置监听事件
	private OnItemClickListener2 onItemClickListener;
	private boolean hasBeenPressed = false;
	private Date initDate;
	private List<Map<String, Integer>> healthData;
	private Context context;

	public CalendarView(Context context) {
		super(context);
		this.context = context;
		init();
	}

	public CalendarView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
		init();
	}

	public CalendarView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		this.context = context;
		init();
	}

	/**
	 * 在日历控件从XML文件初始化完成后，再向其注入其它必须的参数
	 * 
	 * @param date
	 *            记录的当前被选定的日期类型
	 */
	public void setExtraData(Date date) {
		// this.userId = userId2;
		initDate = date;
		init();
		// curDate = selectedStartDate = selectedEndDate = initDate;
		// calendar = Calendar.getInstance();
		// calendar.setTime(curDate);
		// getMonthHealthData(date);
	}

	private void init() {
		if (initDate != null) {
			curDate = selectedStartDate = selectedEndDate = initDate;
			getMonthHealthData(initDate);
			invalidate();
		} else {
			curDate = selectedStartDate = selectedEndDate = new Date();
		}
		calendar = Calendar.getInstance();
		calendar.setTime(curDate);
		surface = new Surface();
		surface.density = getResources().getDisplayMetrics().density;
		setBackgroundColor(surface.bgColor);
		setOnTouchListener(this);
	}

	/**
	 * 根据日期，获取当前月的所有健康数据（显示异常与否）
	 * 
	 * @param date2
	 */
	private void getMonthHealthData(Date date2) {
		// SharedPreferences sp =
		// HealthApplication.getInstance().getSharedPreferences(MyConst.CONFIG_SP_NAME,
		// Context.MODE_PRIVATE);
		// int userId = sp.getInt("currentPickDateUid", -1);
		// String[] start_end = CommonUtil.getYearMonth(date2);
		// url = "SearchIndexInfo" + userId+start_end[0]+start_end[1];
		// String urlCache = CacheUtils.getUrlCache(url,
		// ConfigCacheModel.CONFIG_CACHE_MODEL_LONG, (Activity) context);
		// if(urlCache!=null&&urlCache.length()>0){
		// healthData = JSON.parseObject(urlCache,new
		// TypeReference<List<Map<String,Integer>>>(){});
		// }else{
		// if(NetCheckUtil.checkNet(context))
		// AsyncWebRequest.getInstance("SearchIndexInfo", new String[]{"UserID",
		// "IndexID", "BeginDate", "EndDate"}
		// , new MyPostListener()).execute(new
		// Object[]{userId,"0",start_end[0],start_end[1]},new
		// Object[]{REQUEST_HEALTH_DATA});
		// else
		// healthData = null;
		// }
	}

	/**
	 * 请求健康数据的回调
	 * 
	 * @author wujiankun
	 * 
	 */
	// private class MyPostListener extends OnPostListener{
	// @Override
	// public void onPost(String result, int requestTpye,Context activity) {
	// super.onPost(result, requestTpye,context);
	// if (result == null) {
	// healthData = null;
	// //invalidate();
	// return;
	// }
	// switch (requestTpye) {
	// case REQUEST_HEALTH_DATA:
	// List<HealthDataInfo> HealthDataArray = JSONArray.parseArray(result,
	// HealthDataInfo.class);
	// if(HealthDataArray!=null&&HealthDataArray.size()>0){
	// boolean alreadyExists = false;
	// String pick_date;
	// int isNormal;
	// healthData = new ArrayList<Map<String,Integer>>();
	// for (HealthDataInfo hinfo : HealthDataArray) {
	// pick_date = hinfo.getBusinessDate();
	// isNormal = hinfo.getIsNormal();
	// for (int i = 0;i<healthData.size();i++) {
	// if(healthData.get(i).containsKey(pick_date)){
	// alreadyExists = true;
	// if(isNormal!=0){//更新List中的异常标志位
	// healthData.get(i).put(pick_date, isNormal);
	// }
	// break;
	// }
	// }
	// if(!alreadyExists){
	// HashMap<String, Integer> hashMap = new HashMap<String,Integer>();
	// hashMap.put(pick_date, isNormal);
	// healthData.add(hashMap);
	// }
	// alreadyExists = false;
	// }
	//
	// //缓存Healthdata
	// String healthDataJsonString = JSONArray.toJSONString(healthData);
	// CacheUtils.setUrlCache(healthDataJsonString, url);
	// }else{
	// healthData = null;
	// }
	// invalidate();
	// break;
	// }
	// }
	// }

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		surface.width = getResources().getDisplayMetrics().widthPixels;
		surface.height = (int) (getResources().getDisplayMetrics().heightPixels * 2 / 5);
		widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(surface.width,
				View.MeasureSpec.EXACTLY);
		heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(surface.height,
				View.MeasureSpec.EXACTLY);
		setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		Log.d(TAG, "[onLayout] changed:"
				+ (changed ? "new size" : "not change") + " left:" + left
				+ " top:" + top + " right:" + right + " bottom:" + bottom);
		if (changed) {
			surface.init();
		}
		super.onLayout(changed, left, top, right, bottom);
	}

	List<Map<String, Integer>> copyHealthData = new ArrayList<Map<String, Integer>>();

	@Override
	protected void onDraw(Canvas canvas) {
		Log.d(TAG, "onDraw");
		// 星期背景
		surface.cellBgPaint.setColor(Color.parseColor("#dff2fe"));
		canvas.drawRect(0, surface.weekHeight, surface.width,
				surface.weekHeight - surface.height, surface.cellBgPaint);
		// 星期
		float weekTextY = surface.monthHeight + surface.weekHeight * 3 / 4f;

		for (int i = 0; i < surface.weekText.length; i++) {
			float weekTextX = i
					* surface.cellWidth
					+ (surface.cellWidth - surface.weekPaint
							.measureText(surface.weekText[i])) / 2f;
			canvas.drawText(surface.weekText[i], weekTextX, weekTextY,
					surface.weekPaint);
		}
		// 计算日期
		calculateDate();
		// 按下状态，选择状态背景色
		drawDownOrSelectedBg(canvas);
		// write date number
		// today index
		int todayIndex = -1;
		int dowmDayIndex = -1;
		calendar.setTime(curDate);
		String curYearAndMonth = calendar.get(Calendar.YEAR) + ""
				+ calendar.get(Calendar.MONTH);
		calendar.setTime(selectedStartDate);
		String todayYearAndMonth = calendar.get(Calendar.YEAR) + ""
				+ calendar.get(Calendar.MONTH);
		if (curYearAndMonth.equals(todayYearAndMonth)) {
			int todayNumber = calendar.get(Calendar.DAY_OF_MONTH);
			todayIndex = curStartIndex + todayNumber - 1;
			calendar.setTime(selectedStartDate);
			dowmDayIndex = curStartIndex + calendar.get(Calendar.DAY_OF_MONTH)
					- 1;
		}
		if (healthData != null)
			copyHealthData.addAll(healthData);

		for (int i = 41; i >= 0; i--) {
			int color = surface.textColor;
			if (isLastMonth(i)) {
				color = surface.borderColor;
			} else if (isNextMonth(i)) {
				color = surface.borderColor;
			}
			if (i == todayIndex && !hasBeenPressed) {
				color = surface.selectDateColor;
			} else if (i == downIndex && hasBeenPressed) {
				color = surface.selectDateColor;
			} else if (i == dowmDayIndex && hasBeenPressed) {
				color = surface.selectDateColor;
			}
			drawCellText(canvas, i, date[i] + "", color, copyHealthData);
		}
		super.onDraw(canvas);
	}

	private void calculateDate() {
		calendar.setTime(curDate);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		int dayInWeek = calendar.get(Calendar.DAY_OF_WEEK);
		Log.d(TAG, "day in week:" + dayInWeek);
		int monthStart = dayInWeek;
		if (monthStart == 1) {
			monthStart = 8;
		}
		monthStart -= 1; // 以日为开头-1，以星期一为开头-2
		curStartIndex = monthStart;
		date[monthStart] = 1;
		// last month
		if (monthStart > 0) {
			calendar.set(Calendar.DAY_OF_MONTH, 0);
			int dayInmonth = calendar.get(Calendar.DAY_OF_MONTH);
			for (int i = monthStart - 1; i >= 0; i--) {
				date[i] = dayInmonth;
				dayInmonth--;
			}
			calendar.set(Calendar.DAY_OF_MONTH, date[0]);
		}
		showFirstDate = calendar.getTime();
		// this month
		calendar.setTime(curDate);
		calendar.add(Calendar.MONTH, 1);
		calendar.set(Calendar.DAY_OF_MONTH, 0);
		int monthDay = calendar.get(Calendar.DAY_OF_MONTH);
		for (int i = 1; i < monthDay; i++) {
			date[monthStart + i] = i + 1;
		}
		curEndIndex = monthStart + monthDay;
		// next month
		for (int i = monthStart + monthDay; i < 42; i++) {
			date[i] = i - (monthStart + monthDay) + 1;
		}
		if (curEndIndex < 42) {
			// 显示了下一月的
			calendar.add(Calendar.DAY_OF_MONTH, 1);
		}
		calendar.set(Calendar.DAY_OF_MONTH, date[41]);
		showLastDate = calendar.getTime();
	}

	/**
	 * 普通日期的绘制方法（可在此方法中改变指定日期的背景色）
	 * 
	 * @param canvas
	 * @param index
	 * @param text
	 * @param copyHealthData2
	 */
	private void drawCellText(Canvas canvas, int index, String text, int color,
			List<Map<String, Integer>> copyHealthData2) {
		int x = getXByIndex(index);
		int y = getYByIndex(index);
		surface.datePaint.setColor(color);
		float cellY = surface.monthHeight + surface.weekHeight + (y - 1)
				* surface.cellHeight + surface.cellHeight * 3 / 4f;
		float cellX = (surface.cellWidth * (x - 1))
				+ (surface.cellWidth - surface.datePaint.measureText(text))
				/ 2f;
		if (copyHealthData2 != null && copyHealthData2.size() > 0
				&& index < curEndIndex) {
			String date;
			String mtext = text;
			if (text.length() < 2) {
				mtext = "0" + text;
			}
			for (int i = copyHealthData2.size() - 1; i >= 0; i--) {
				for (String key : copyHealthData2.get(i).keySet()) {
					date = key.split("-")[2];
					if (date.equals(mtext)) {// 此天已经包含数据
						if (copyHealthData2.get(i).get(key) != 0) {// 此天不仅包含数据，而且异常
							drawCellBg(canvas, index,
									Color.parseColor("#ffe9e4"));
							copyHealthData2.remove(i);
							break;
						}
						drawCellBg(canvas, index, Color.parseColor("#dff2fe"));
						copyHealthData2.remove(i);
						break;
					}
				}
			}
		}
		canvas.drawText(text, cellX, cellY, surface.datePaint);
	}

	/**
	 * 
	 * @param canvas
	 * @param index
	 * @param color
	 */
	private void drawCellBg(Canvas canvas, int index, int color) {
		int x = getXByIndex(index);
		int y = getYByIndex(index);
		surface.cellBgPaint.setColor(color);
		float left = surface.cellWidth * (x - 1) + surface.borderWidth;
		float top = surface.monthHeight + surface.weekHeight + (y - 1)
				* surface.cellHeight + surface.borderWidth;
		// 画圆背景
		canvas.drawCircle(
				(left * 2 + surface.cellWidth - surface.borderWidth) / 2,
				(top * 2 + surface.cellHeight - surface.borderWidth + 2) / 2,
				(surface.cellHeight - surface.borderWidth) / 2,
				surface.cellBgPaint);
	}

	private void drawDownOrSelectedBg(Canvas canvas) {
		// down and not up
		if (downDate != null) {
			drawCellBg(canvas, downIndex, surface.cellDownColor);
		}
		// selected bg color
		if (!selectedEndDate.before(showFirstDate)
				&& !selectedStartDate.after(showLastDate)) {
			int[] section = new int[] { -1, -1 };
			calendar.setTime(curDate);
			calendar.add(Calendar.MONTH, -1);
			findSelectedIndex(0, curStartIndex, calendar, section);
			if (section[1] == -1) {
				calendar.setTime(curDate);
				findSelectedIndex(curStartIndex, curEndIndex, calendar, section);
			}
			if (section[1] == -1) {
				calendar.setTime(curDate);
				calendar.add(Calendar.MONTH, 1);
				findSelectedIndex(curEndIndex, 42, calendar, section);
			}
			if (section[0] == -1) {
				section[0] = 0;
			}
			if (section[1] == -1) {
				section[1] = 41;
			}
			for (int i = section[0]; i <= section[1]; i++) {
				drawCellBg(canvas, i, surface.cellSelectedColor);
			}
		}
	}

	private void findSelectedIndex(int startIndex, int endIndex,
			Calendar calendar, int[] section) {
		for (int i = startIndex; i < endIndex; i++) {
			calendar.set(Calendar.DAY_OF_MONTH, date[i]);
			Date temp = calendar.getTime();
			// Log.d(TAG, "temp:" + temp.toLocaleString());
			if (temp.compareTo(selectedStartDate) == 0) {
				section[0] = i;
			}
			if (temp.compareTo(selectedEndDate) == 0) {
				section[1] = i;
				return;
			}
		}
	}

	public Date getSelectedStartDate() {
		return selectedStartDate;
	}

	public Date getSelectedEndDate() {
		return selectedEndDate;
	}

	private boolean isLastMonth(int i) {
		if (i < curStartIndex) {
			return true;
		}
		return false;
	}

	private boolean isNextMonth(int i) {
		if (i >= curEndIndex) {
			return true;
		}
		return false;
	}

	private int getXByIndex(int i) {
		return i % 7 + 1; // 1 2 3 4 5 6 7
	}

	private int getYByIndex(int i) {
		return i / 7 + 1; // 1 2 3 4 5 6
	}

	// 获得当前应该显示的年月
	public String getYearAndmonth() {
		calendar.setTime(curDate);
		int year = calendar.get(Calendar.YEAR);
		int month = calendar.get(Calendar.MONTH);
		return year + "-" + surface.monthText[month];
	}

	// 上一月
	public String clickLeftMonth() {
		calendar.setTime(curDate);
		calendar.add(Calendar.MONTH, -1);
		curDate = calendar.getTime();
		getMonthHealthData(curDate);
		downIndex = -1;
		invalidate();
		return getYearAndmonth();
	}

	// 下一月
	public String clickRightMonth() {
		calendar.setTime(curDate);
		calendar.add(Calendar.MONTH, 1);
		curDate = calendar.getTime();
		getMonthHealthData(curDate);
		downIndex = -1;
		invalidate();
		return getYearAndmonth();
	}

	private void setSelectedDateByCoor(float x, float y) {
		// cell click down
		if (y > surface.monthHeight + surface.weekHeight) {
			int m = (int) (Math.floor(x / surface.cellWidth) + 1);
			int n = (int) (Math
					.floor((y - (surface.monthHeight + surface.weekHeight))
							/ Float.valueOf(surface.cellHeight)) + 1);
			downIndex = (n - 1) * 7 + m - 1;
			Log.d(TAG, "downIndex:" + downIndex);
			calendar.setTime(curDate);
			if (isLastMonth(downIndex)) {
				calendar.add(Calendar.MONTH, -1);
			} else if (isNextMonth(downIndex)) {
				calendar.add(Calendar.MONTH, 1);
			}
			calendar.set(Calendar.DAY_OF_MONTH, date[downIndex]);
			downDate = calendar.getTime();
		}
		hasBeenPressed = true;// TODO 设置点击标记为真，在接下来的onDraw()过程中，设置当前日期为普通日期的颜色
		invalidate();
	}

	// private OnMonthChangeListener monthChangeListener;
	interface OnMonthChangeListener {
		void onMonthChange(String[] ym);
	}

	public void setMonthChangeListener(OnMonthChangeListener monthChangeListener) {
		// this.monthChangeListener = monthChangeListener;
	}

	float y1 = 0;
	float y2 = 0;
	float y3 = 0;
	// private int userId;
	private String url;

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		switch (event.getAction()) {

		case MotionEvent.ACTION_DOWN:
			setSelectedDateByCoor(event.getX(), event.getY());
			y1 = event.getY();
			break;
		// case MotionEvent.ACTION_MOVE:
		// y2 = event.getY();
		// if(y1-y2>150){
		// String[] year_month = clickRightMonth().split("-");
		// monthChangeListener.onMonthChange(year_month);
		// y1=y2;
		// }else if(y2-y1>150){
		// String[] year_month =clickLeftMonth().split("-");
		// monthChangeListener.onMonthChange(year_month);
		// y1=y2;
		// }
		// break;
		case MotionEvent.ACTION_UP:
			boolean isclick = false;
			y3 = event.getY();
			if (Math.abs(y3) - Math.abs(y1) > -5
					&& Math.abs(y3) - Math.abs(y1) < 5) {
				isclick = true;
			}
			if (downDate != null && downDate.after(new Date())) {
				return true;// 如果日期处于今天日期的后面，则不响应点击
			}
			if (downDate != null && isclick) {
				selectedStartDate = selectedEndDate = downDate;
				// 响应监听事件
				onItemClickListener.OnItemClick(selectedStartDate);
				downDate = null;
				invalidate();
			}
			y1 = 0;
			y2 = 0;
			break;
		}
		return true;
	}

	// 给控件设置监听事件
	public void setOnItemClickListener(OnItemClickListener2 onItemClickListener) {
		this.onItemClickListener = onItemClickListener;
	}

	// 监听接口
	public interface OnItemClickListener2 {
		void OnItemClick(Date date);
	}

	/**
	 * 
	 * 1. 布局尺寸 2. 文字颜色，大小 3. 当前日期的颜色，选择的日期颜色
	 */
	private class Surface {
		public float density;
		public int width; // 整个控件的宽度
		public int height; // 整个控件的高度
		public float monthHeight; // 显示月的高度
		public float weekHeight; // 显示星期的高度
		public float cellWidth; // 日期方框宽度
		public float cellHeight; // 日期方框高度
		public float borderWidth;
		public int bgColor = Color.parseColor("#FFFFFF");
		private int textColor = Color.BLACK;
		private int btnColor = Color.parseColor("#666666");
		private int borderColor = Color.parseColor("#CCCCCC");
		public int selectDateColor = Color.WHITE;
		public int cellDownColor = Color.parseColor("#CCFFFF");
		public int cellSelectedColor = Color.parseColor("#f16c50");
		public Paint borderPaint;
		public Paint monthPaint;
		public Paint weekPaint;
		public Paint datePaint;
		public Paint monthChangeBtnPaint;
		public Paint cellBgPaint;

		public String[] weekText = { "日", "一", "二", "三", "四", "五", "六" };
		public String[] monthText = { "01", "02", "03", "04", "05", "06", "07",
				"08", "09", "10", "11", "12" };

		public void init() {
			float temp = height / 7f;
			monthHeight = 0;// (float) ((temp + temp * 0.3f) * 0.6);
			weekHeight = (float) ((temp + temp * 0.3f) * 0.7);
			cellHeight = (height - monthHeight - weekHeight) / 6f;// cellHeight
																	// = (height
																	// -
																	// monthHeight
																	// -
																	// weekHeight)
																	// / 6f;
			cellWidth = width / 7f;
			borderPaint = new Paint();
			borderPaint.setColor(borderColor);
			borderPaint.setStyle(Paint.Style.STROKE);
			borderWidth = (float) (0.5 * density);
			borderWidth = borderWidth < 1 ? 1 : borderWidth;
			borderPaint.setStrokeWidth(borderWidth);
			monthPaint = new Paint();
			monthPaint.setColor(textColor);
			monthPaint.setAntiAlias(true);
			float textSize = cellHeight * 0.4f;// float textSize = cellHeight *
												// 0.4f;
			Log.d(TAG, "text size:" + textSize);
			monthPaint.setTextSize(textSize);
			monthPaint.setTypeface(Typeface.DEFAULT_BOLD);
			weekPaint = new Paint();
			weekPaint.setColor(textColor);
			weekPaint.setAntiAlias(true);
			float weekTextSize = weekHeight * 0.6f;
			weekPaint.setTextSize(weekTextSize);
			weekPaint.setTypeface(Typeface.DEFAULT_BOLD);
			datePaint = new Paint();
			datePaint.setColor(textColor);
			datePaint.setAntiAlias(true);
			float cellTextSize = cellHeight * 0.55f;// float cellTextSize =
													// cellHeight * 0.5f;
			datePaint.setTextSize(cellTextSize);
			datePaint.setTypeface(Typeface.DEFAULT);
			monthChangeBtnPaint = new Paint();
			monthChangeBtnPaint.setAntiAlias(true);
			monthChangeBtnPaint.setStyle(Paint.Style.FILL_AND_STROKE);
			monthChangeBtnPaint.setColor(btnColor);
			cellBgPaint = new Paint();
			cellBgPaint.setAntiAlias(true);
			cellBgPaint.setStyle(Paint.Style.FILL);
			cellBgPaint.setColor(cellSelectedColor);
		}
	}
}
